package com.fzu.mmdbproxyframework.cluster;


import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.fzu.mmdbproxyframework.mmdb.h2.H2DB;
import com.fzu.mmdbproxyframework.model.DBInterf;
import com.fzu.mmdbproxyframework.model.DataNode;
import com.fzu.mmdbproxyframework.model.DataSource;
import com.fzu.mmdbproxyframework.model.MMDataNodeCluster;
import com.fzu.mmdbproxyframework.model.MysqlDB;
import com.fzu.mmdbproxyframework.model.Table;
import com.fzu.mmdbproxyframework.model.VM;
import com.fzu.mmdbproxyframework.multitask.Failover;
import com.fzu.mmdbproxyframework.multitask.ScheduledTaskExecutor;
import com.fzu.mmdbproxyframework.util.UniqueStringGenerator;

public class ClusterManager {
	public MMDataNodeCluster cluster; 
	private ScheduledTaskExecutor ClusterHeartbeatTask;
	private ScheduledTaskExecutor MMDBFullDumpTask;
	/**
	 * @param cluster
	 */
	public ClusterManager(MMDataNodeCluster cluster) {
		super();
		this.cluster = cluster;
	}
	//启动MMDB服务
	public  void startMMDataNodeServer() throws IOException, SQLException{
		for(DataNode datanode:cluster.getClusterContext().getMMDataNodeList()){
			datanode.startmmDBServer();
//			System.out.println("----datanode.startmmDBServer()之后------");
			//查看创好虚拟机之后  MMDBDATANode 中的datasource是否可用
			for(DataSource datasource:datanode.getDb().getDataSourceList()){
//				System.out.println("查看startmmDBServer之后  MMDBDATANode 中的datasource是否可用="+datasource.getConnection().hashCode());
				if(datasource.getConnection().hashCode() != 0){
					datanode.getDb().setActive(true);
				}else{
					datanode.getDb().setActive(false);
				}
			}
		}
	}
	//将创建好的vm和MMdatanode关联起来
	public  void createVMByMMDataNode() throws SQLException{
		System.out.println("createVMByMMDataNode 之前.getVMList()="+cluster.getClusterContext().getVMList().size());
		for(DataNode datanode:cluster.getClusterContext().getMMDataNodeList()){
			VM vm =VmManager.creatVM();//创建虚拟机
			if(vm.isCreateSuccess()){
				datanode.setVmIP(vm.getIp());
				datanode.setVmName(vm.getUserName());
				datanode.setVmPasswd(vm.getUserPasswd());
				datanode.setDataNodeuuid(vm.getUuid());
				cluster.getClusterContext().getVMList().add(vm);
			}
		}
		System.out.println("createVMByMMDataNode之后 .getVMList()="+cluster.getClusterContext().getVMList().size());

	}
	//将MMDB和DataNode对应起来  而且将DataNode设置到MMDB中的datasource   此时还没有创虚拟机  所以datasource中的DataNode ip为空
	public  void createDataNode_SetTableToDataNode() throws SQLException{
		System.out.println("distributeMMDB_DataNode cluster.getClusterContext().getMMDBNodeList()="+cluster.getClusterContext().getMMDBNodeList().size());
		
		//创建mmDataNode
		for(DBInterf mmDB:cluster.getClusterContext().getMMDBNodeList()){
			H2DB h2db = (H2DB)mmDB;
			DataNode mmdatanode = new DataNode();
			mmdatanode.setDb(h2db);
			mmdatanode.setDataNodeName(UniqueStringGenerator.generateRandomString("mmdatanode_"));
			
			for(DataSource datasource : h2db.getDataSourceList()){
				datasource.setDatanode(mmdatanode);
			}
			cluster.getClusterContext().getMMDataNodeList().add(mmdatanode);
		}
		
		System.out.println("cluster.getClusterContext().getSourceDBNodeList().size()="+cluster.getClusterContext().getSourceDBNodeList().size());
		if(cluster.getConfigContext().getAllTables().equalsIgnoreCase("true")){
			for(DBInterf sourcedb:cluster.getClusterContext().getSourceDBNodeList()){
				MysqlDB mysqlDB = (MysqlDB)sourcedb;
//				System.out.println("mysqlDB.getDataSourceList().size()="+mysqlDB.getDataSourceList().size());
				List<Table> tableList = mysqlDB.creatTableList();
				for(DataNode MMDataNode:cluster.getClusterContext().getMMDataNodeList()){
					H2DB h2db = (H2DB)MMDataNode.getDb();
					h2db.setTableList(tableList);
				}
				
			}
		}else{
			for(DBInterf sourcedb:cluster.getClusterContext().getSourceDBNodeList()){
				MysqlDB mysqlDB = (MysqlDB)sourcedb;
				List<Table> tableList = mysqlDB.creatTableList();
				for(DataNode MMDataNode:cluster.getClusterContext().getMMDataNodeList()){
					DBInterf h2db = MMDataNode.getDb();
					for(String name:h2db.getTableNameList()){
						for(Table Mysqltable :tableList){
							if(Mysqltable.getName().equalsIgnoreCase(name)){
								h2db.getTableList().add(Mysqltable);
							}
						}
					}
				}
				
			}
		}
		
		System.out.println("cluster.getClusterContext().getMMDataNodeList="+cluster.getClusterContext().getMMDataNodeList().size());
		
	}
	//在MMDataNode构建表
	public void createTableInAllMMDataNode() throws SQLException{
		System.out.println("在MMDataNode构建表");
		for(DataNode datanode : cluster.getClusterContext().getMMDataNodeList()){
			for(Table table:datanode.getDb().getTableList()){
				Connection conn = datanode.getDb().getConnection();
				System.out.println("查看所有的  MMDBDATANode 中的datasource是否可用="+conn.hashCode());
				Statement sta = conn.createStatement();
				String str = table.mysql_createTableSql();
				sta.executeUpdate(str);
//				System.out.println("buildTableInMMDataNode= mysql_createTableSql ="+str);
			}
		}
	}
//	
//	//删除一个MMDataNode的list 包括删除虚拟机  和 的mmDataNode  MMDBNode
//	public static void deleteMMDataNodeList(List<DataNode> deleteMMDataNodeList){
//		List<DataNode> MMDataNodeList =  cluster.getClusterContext().getMMDataNodeList();
//		List<DBInterf> mmDBNodeList= cluster.getClusterContext().getMMDBNodeList();
//		List<VM> vmList = cluster.getClusterContext().getVMList();
//		for(DataNode deleteMMDataNode:deleteMMDataNodeList){
//			for(DataNode mmDataNode: MMDataNodeList){
//				if(	deleteMMDataNode.equals(mmDataNode)){
//					VmManager.deleteVM(mmDataNode.getDataNodeuuid());//删除虚拟机
//					//从MMDataNodeList中删除
//					MMDataNodeList.remove(mmDataNode);
//					//从MMDB中删除
//					for(DBInterf db : mmDBNodeList){
//						if(mmDataNode.getDb().equals(db)){
//							MMDataNodeList.remove(db);
//						}
//					}
//					//从VMlist删除
//					for(VM vm: vmList){
//						if(vm.getIp().equalsIgnoreCase(mmDataNode.getVmIP())){
//							vmList.remove(vm);
//						}
//					}
//					
//				}
//			}
//			
//		}
//		
//		
//	}
	
	//可以在运行期间删除MMDataNode  包括删除虚拟机  和 的mmDataNode  MMDBNode
	public  void deleteMMDataNode(String ip){
		System.out.println("删除"+ip+"之前 getMMDataNodeList().size()"+cluster.getClusterContext().getMMDataNodeList().size());
		System.out.println("删除"+ip+"之前 getMMDBNodeList().size()"+cluster.getClusterContext().getMMDBNodeList().size());
		System.out.println("删除"+ip+"之前 getVMList().size()"+cluster.getClusterContext().getVMList().size());
		
		List<DataNode> mmDataNodeList = cluster.getClusterContext().getMMDataNodeList();
		List<DBInterf> mmDBNodeList= cluster.getClusterContext().getMMDBNodeList();
		List<VM> vmList = cluster.getClusterContext().getVMList();
		
		Iterator<DataNode> mmDataNodeiter = mmDataNodeList.iterator();  
		Iterator<DBInterf> mmDBNodeiter = mmDBNodeList.iterator();  
		Iterator<VM> vmiter = vmList.iterator();  

		
		while(mmDataNodeiter.hasNext()){  
			System.out.println("mmDataNodeiter.hasNext()"+mmDataNodeList.size());
			DataNode mmDataNode = mmDataNodeiter.next();  
		    if(mmDataNode.getVmIP().equalsIgnoreCase(ip)){ 
		    	//从MMDataNodeList中删除
		    	mmDataNodeiter.remove();  
		    }  
		    
		    //从MMDB中删除
		    while(mmDBNodeiter.hasNext()){
		    	DBInterf mmdb = mmDBNodeiter.next();  
		    	if(mmDataNode.getDb().equals(mmdb)){
		    		mmDBNodeiter.remove();
		    	}
		    }
		  //从VMlist删除
		    while(vmiter.hasNext()){
		    	VM vm = vmiter.next();  
		    	if(vm.getIp().equalsIgnoreCase(ip)){
		    		//将虚拟机删除
			    	VmManager.deleteVM(vm.getUuid());
		    		vmiter.remove();
		    	}
		    }
		    
			System.out.println("删除之后mmDataNodeList.size()"+mmDataNodeList.size());
		}  
		
		System.out.println("删除"+ip+"之后 getMMDataNodeList().size()"+cluster.getClusterContext().getMMDataNodeList().size());
		System.out.println("删除"+ip+"之后 getMMDBNodeList().size()"+cluster.getClusterContext().getMMDBNodeList().size());
		System.out.println("删除"+ip+"之后 getVMList().size()"+cluster.getClusterContext().getVMList().size());
		
	}
	//包括创建MMDB  和创建MMDataNode  创建vm  
	public  DataNode addMMDBDataNode(Map<String,String> MMDBParam,List<String> tableNameList){
			  DBInterf DBNode = null;
			  if(MMDBParam.get("type").equalsIgnoreCase("h2")){
				  DBNode = new H2DB(cluster);
			  }else{
				  System.out.println("qita=-数据ku类型"); 
			  }
			  DBNode.setMode(MMDBParam.get("mode"));
			  DBNode.setDBNodeName(MMDBParam.get("name"));
			  DBNode.setDBNodeType(MMDBParam.get("type"));
			  DataSource dataSource = new DataSource(cluster);
			  dataSource.setDataSourcename(MMDBParam.get("dataSource_name"));
			  dataSource.setType(MMDBParam.get("dataSource_type"));
			  dataSource.setDBType(MMDBParam.get("dataSource_dbType"));
			  dataSource.setDBmode(MMDBParam.get("dataSource_dbMode"));
			  dataSource.setShutdown(false);
			  if(cluster.getConfigContext().getAllTables().equalsIgnoreCase("false")){
				  DBNode.setTableNameList(tableNameList);
			  }
			  DBNode.getDataSourceList().add(dataSource);//添加多个dataSourceNodes信息
//考虑要不要把MMDBNode加入			 
			  cluster.getClusterContext().getMMDBNodeList().add(DBNode);//加入用户上下文环境  
			  
			DataNode mmdatanode = new DataNode();
			mmdatanode.setDb(DBNode);
			mmdatanode.setDataNodeName(UniqueStringGenerator.generateRandomString("mmdatanode_"));
			
			for(DataSource datasource : DBNode.getDataSourceList()){
				datasource.setDatanode(mmdatanode);
			}
			
			
			VM vm =VmManager.creatVM();//创建虚拟机
			if(vm.isCreateSuccess()){
				mmdatanode.setVmIP(vm.getIp());
				mmdatanode.setVmName(vm.getUserName());
				mmdatanode.setVmPasswd(vm.getUserPasswd());
				mmdatanode.setDataNodeuuid(vm.getUuid());
				cluster.getClusterContext().getVMList().add(vm);
			}
			
		
		cluster.getClusterContext().getMMDataNodeList().add(mmdatanode);			  
		System.out.println("after addMMDBDataNode cluster.getClusterContext().getMMDataNodeList()="+cluster.getClusterContext().getMMDataNodeList().size());
		return mmdatanode;
	}
	
	// 启动其中的数据库服务  创建数据库表    传输数据  添加心跳表
	public  void initMMDBDataNode(DataNode mmdatanode) throws SQLException, IOException{
		mmdatanode.startmmDBServer();
		for(DataSource datasource:mmdatanode.getDb().getDataSourceList()){
			System.out.println("测试数据库服务是否启动成功");
			if(datasource.getConnection().hashCode() != 0){
				mmdatanode.getDb().setActive(true);
			}else{
				mmdatanode.getDb().setActive(false);
			}
		}
		System.out.println("开始创建表--createTableInMMDataNode(mmdatanode)---");
		this.createTableInMMDataNode(mmdatanode);
//		添加心跳表
		new Failover(cluster).creatHeartbeatTableInMMDB(mmdatanode);
		System.out.println("开始传输数据");
		this.transferDataToMMDataNode(mmdatanode);
	}
	public  void stopMMDBDataNodeServer(DataNode MMDBDataNode) throws IOException, SQLException{
		MMDBDataNode.startmmDBServer();
	}
	public  void transferDataToAllMMDBDataNode() throws SQLException{
		
		for(DataNode datanode :cluster.getClusterContext().getMMDataNodeList()){
			DBInterf h2db = datanode.getDb();
			Connection conn =  h2db.getConnection();
			Statement sta = conn.createStatement();
			for(Table table:h2db.getTableList()){
				for(DBInterf mysqlDB:cluster.getClusterContext().getSourceDBNodeList()){
					MysqlDB sourcemysqlDB =	(MysqlDB)mysqlDB;
					List<String> insert_sql_List = sourcemysqlDB.create_insertSqlByTable(table);
					for(String str:insert_sql_List){
						sta.executeUpdate(str);
	//					System.out.println("transferDataFromDataSourceToMMDB == insert_sql="+str);
					}
				}
			}
			
		}
	}
	//在已经启动内存数据库的  MMDataNode创建表 
	public  void createTableInMMDataNode(DataNode MMDataNode) throws SQLException{
		//将内存数据库中添加表对象
		DBInterf h2db = MMDataNode.getDb();
		if(cluster.getConfigContext().getAllTables().equalsIgnoreCase("true")){
			for(DBInterf sourcedb:cluster.getClusterContext().getSourceDBNodeList()){
				MysqlDB mysqlDB = (MysqlDB)sourcedb;
//				System.out.println("mysqlDB.getDataSourceList().size()="+mysqlDB.getDataSourceList().size());
				List<Table> tableList = mysqlDB.creatTableList();
			
				h2db.setTableList(tableList);
				
			}
		}else{
			for(DBInterf sourcedb:cluster.getClusterContext().getSourceDBNodeList()){
				MysqlDB mysqlDB = (MysqlDB)sourcedb;
				System.out.println("mysqlDB.getDataSourceList().size()="+mysqlDB.getDataSourceList().size());
				List<Table> tableList = mysqlDB.creatTableList();
				for(String name:h2db.getTableNameList()){
					System.out.println("getTableNameList name="+name);
					for(Table Mysqltable :tableList){
						if(Mysqltable.getName().equalsIgnoreCase(name)){
							h2db.getTableList().add(Mysqltable);
						}
					}
				}
			}
		}
		
		//开始将内存数据库中的表对象 进行创建
		for(Table table:h2db.getTableList()){
			Connection conn = h2db.getConnection();
			System.out.println("查看所有的  MMDBDATANode 中的datasource是否可用="+conn.hashCode());
			Statement sta = conn.createStatement();
			String str = table.mysql_createTableSql();
			sta.executeUpdate(str);
//			System.out.println("buildTableInMMDataNode= mysql_createTableSql ="+str);
		}
		
	}
	//在已经创建好表的内存数据库服务中传输数据源的数据   数据源只有一个(MysqlDB)cluster.getClusterContext().getSourceDBNodeList().getFirst();
	public  void transferDataToMMDataNode(DataNode MMDataNode) throws SQLException{
		
			DBInterf h2db = MMDataNode.getDb();
			Connection conn =  h2db.getConnection();
			Statement sta = conn.createStatement();
			System.out.println("transferDataToMMDataNode h2db.getTableList().size()="+h2db.getTableList().size());
			for(Table table:h2db.getTableList()){
				System.out.println(table);
				for(DBInterf sourcedb:cluster.getClusterContext().getSourceDBNodeList()){
					MysqlDB sourcemysqlDB =	(MysqlDB)sourcedb;
					List<String> insert_sql_List = sourcemysqlDB.create_insertSqlByTable(table);
					for(String str:insert_sql_List){
						sta.executeUpdate(str);
	//					System.out.println("transferDataFromDataSourceToMMDB == insert_sql="+str);
					}
				}
			}
	}
	

	public void setHeartBeatstart() {
		cluster.getHeartbeatTask().setStop(false);
	}
	
	public void setHeartBeatstop(){
		cluster.getHeartbeatTask().setStop(true);
	}
	//创建心跳任务
	public void startHeartBeat(){
		if(ClusterHeartbeatTask == null){
			ClusterHeartbeatTask = new ScheduledTaskExecutor(cluster.getHeartbeatTask()); 
		}
		ClusterHeartbeatTask.execute();
		
	}
	public void startFullDumpTask(){
		if(MMDBFullDumpTask == null){
			MMDBFullDumpTask = new ScheduledTaskExecutor(cluster.getFullDumpTask()); 
		}
		MMDBFullDumpTask.execute();
		
	}
	
	
}
